#include "GUITextbox.h"
#include "IRenderer.h"
#include "Matrix.h"
#include "OnKeyPressEvent.h"
#include "OnMouseLeftDownEvent.h"
#include "GUIWindow.h"

GUITextbox::GUITextbox()
{
	m_cursorLocation = 0;
	m_fontColor = 0x00000000;
	m_font = HashedString("Arial");
	m_visible = true;
	m_enabled = true;
	m_dimensions = Maths::Point<unsigned int>(1, 1);
}

void GUITextbox::DefaultText( std::string& defaultText )
{
	m_defaultText = defaultText;
}

std::string GUITextbox::DefaultText() const
{
	return m_defaultText;
}

bool GUITextbox::ReceiveEvent( IEvent& event )
{
	if (m_enabled && m_visible)
	{
#pragma region KeyInput
		if (event.Type() == OnKeyPressEvent::type)
		{
			OnKeyPressEvent& keyEvent = static_cast<OnKeyPressEvent&>(event);
			if (keyEvent.isVirtual())
			{
				if (keyEvent.Key() == 8)				// Backspace
				{
					if (m_cursorLocation > 0)
					{
						unsigned int offset = --m_cursorLocation;
						m_text.erase(offset, 1);
					}
				} else if (keyEvent.Key() == 39)		// Arrow
				{
					if (m_cursorLocation < m_text.size())
						++m_cursorLocation;
				} else if (keyEvent.Key() == 37)		// Arrow
				{
					if (m_cursorLocation > 0)
						--m_cursorLocation;
				} else if (keyEvent.Key() == 38 || keyEvent.Key() == 40)	// Up down arrows (same as end/home key?)
				{
				} else if (keyEvent.Key() == 46)		// Delete
				{
					if (m_cursorLocation < m_text.size())
					{
						unsigned int offset = m_cursorLocation;
						m_text.erase(offset, 1);
					}
				} 
			} else
			{
				char key = keyEvent.Key();
				switch (key)
				{
				case 9:					// Tab Key
				case 8:					// Backspace Key
				case 13:				// Enter key
					{
					return false;
					}
				}
				m_text.insert(m_cursorLocation++, &keyEvent.Key(), 1);
			}
			return true;			// consume event
		}
#pragma endregion
#pragma region MouseInput
		else if (event.Type() == OnMouseLeftDownEvent::type)
		{
			OnMouseLeftDownEvent& mouseEvent = static_cast<OnMouseLeftDownEvent&>(event);
			int x = mouseEvent.Coords().X;
			int y = mouseEvent.Coords().Y;
			int absX = m_location.X + (int)m_parentLocation.X;
			int absY = m_location.Y + m_parentLocation.Y;
		
			if ((x > absX) && (x < absX + (int)m_dimensions.X) &&
				(y > absY) && (y < absY + (int)m_dimensions.Y))
			{
				m_parent->ActiveObject(this);
				return true;			// consume event
			} else
			{
				if (m_parent->ActiveObject() == this)
					m_parent->ActiveObject(0);
				return false;
			}
		}
#pragma endregion
	}
	return false;
}

void GUITextbox::Paint()
{
	if (m_visible)
	{
		// Render background
		Maths::Matrix transform;
		transform.Translate((float)m_location.X, (float)m_location.Y, 0.0f);
		transform.Scale((float)m_dimensions.X, (float)m_dimensions.Y, 1.0f);

		Renderer->SetColor(0xFFDDDDDD);
		Renderer->PushTexture(m_background);
		Renderer->PushModelViewMatrix(transform);
		Renderer->Render(*(m_shape.getShape()));
		Renderer->PopModelViewMatrix();
		Renderer->PopTexture();
		Renderer->SetColor(0xFFFFFFFF);

		// Render foreground with text
		transform.Identity();
		transform.Translate(m_location.X+2, m_location.Y+2, 0.0f);
		transform.Scale(m_dimensions.X-4, m_dimensions.Y-4, 1.0f);

		Renderer->PushTexture(m_background);
		Renderer->PushModelViewMatrix(transform);
		Renderer->Render(*(m_shape.getShape()));
		std::string text = m_text.size() > 0 ? m_text : m_defaultText;
		if (m_parent->ActiveObject() == this)
		{
			if (text.size() < m_cursorLocation)
				m_cursorLocation = 0;
			text.insert(m_cursorLocation, "|");
		}
		Renderer->PrintFont(m_font, m_fontColor, m_parentLocation.X + m_location.X+4, m_parentLocation.Y + m_location.Y+4, text.c_str());
		Renderer->PopModelViewMatrix();
		Renderer->PopTexture();
	}
}
void GUITextbox::Text( std::string& title )
{
	m_text = title;
	if (title.size() < m_cursorLocation)
		m_cursorLocation = title.size();
}

std::string GUITextbox::Text() const
{
	return m_text;
}

void GUITextbox::Font( std::string& font )
{
	m_font = HashedString(font);
}

void GUITextbox::Font( HashedString& font )
{
	m_font = font;
}

HashedString GUITextbox::Font() const
{
	return m_font;
}

void GUITextbox::FontColor( unsigned int color )
{
	m_fontColor = color;
}

unsigned int GUITextbox::FontColor() const
{
	return m_fontColor;
}

void GUITextbox::Background( std::string& background )
{
	m_background = HashedString(background);
}

void GUITextbox::Background( HashedString& background )
{
	m_background = background;
}

HashedString GUITextbox::Background() const
{
	return m_background;
}